package com.better.frontend.service.exam;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.better.backend.dataComputingService.model.stuScore.ExamStudentScoreCalModel;
import com.better.backend.dataComputingService.repository.stuScoreRespository.ExamStuScoRepsitory;
import com.better.backend.mqReceiverService.examReceiver.model.ExamModel;
import com.better.backend.mqReceiverService.examReceiver.model.ExamUnitModel;
import com.better.backend.mqReceiverService.examReceiver.model.SubjectScoreModel;
import com.better.common.base.ServiceResponse;
import com.better.common.exception.DescribeException;
import com.better.common.exception.ExceptionEnum;
import com.better.common.jwtauth.secruity.JWTUserDetails;
import com.better.common.mongo.model.SpringDataPageable;
import com.better.common.utils.CmsHttpPostUtil;
import com.better.common.utils.ServiceResponseHandle;
import com.better.common.utils.SessionUtils;
import com.better.consist.CalTypeEnum;
import com.better.consist.ExamEnum;
import com.better.frontend.Iservice.exam.ExamService;
import com.better.frontend.model.exam.ClassChildVo;
import com.better.frontend.model.exam.GradeAndClassVo;
import com.better.frontend.model.index.IndexParam;
import com.better.frontend.repository.exam.ExmpRepsitory;
import com.better.frontend.repository.grade.GradeRelationSubjectRepsitory;
import com.better.frontend.vo.exam.ExamVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by wfm on 2017/11/11.
 */
@Service
public class ExamServiceImp implements ExamService {
    @Resource
    private ExmpRepsitory exmpRepsitory;
    @Resource
    private GradeRelationSubjectRepsitory gradeRelationSubjectRepsitory;
    @Value("${classListUrl}")
    private String classListUrl;
    @Autowired
    private ExamStuScoRepsitory examStuScoRepsitory;

    /**
     * 获取所有考试信息
     *
     * @author:
     * @date :2017/11/8
     */
    @Override
    public List<ExamModel> getAllExam(IndexParam examParam) {
        Map<String, Object> pamMap = new HashMap<>();
        Map<String, Integer> sortMap = new HashMap<>();
        Map<String, Object> includMap = new HashMap<>();
        if (!StringUtils.isEmpty(examParam.getExamType())) {
            pamMap.put("examType", examParam.getExamType());
        }
        pamMap.put("status", ExamEnum.EXAM_STATUS_PUBLISH.getCode().toString());
        if (CalTypeEnum.examtype_school.equals(examParam.getExamType())) {
            pamMap.put("examUnitModels.unitId", examParam.getUnitId());
        } else {
            pamMap.put("gradeId", examParam.getUnitId());
        }
        sortMap.put("endDate", 0);
        includMap.put("id", null);
        includMap.put("examName", null);
        List<ExamModel> reList = exmpRepsitory.findListBy(pamMap, sortMap, includMap);
        List<ExamModel> newList = reList.stream().filter(e -> !e.getId().equals(examParam.getSourceExamId()))
                .collect(Collectors.toList());
        return newList;
    }

    @Override
    public ExamVo getExmp(IndexParam examParam) {
        JWTUserDetails user = SessionUtils.getUserInfo();
        Map<String, Object> paramMap = new HashMap<String, Object>();
        Page<ExamModel> examModels = null;
        Map<String, Object> schoolParamMap = new HashMap<String, Object>();
        schoolParamMap.put("schoolId", user.getSchoolId());
        schoolParamMap.put("examType", CalTypeEnum.examtype_school);
        Map<String, Object> classParamMap = new HashMap<String, Object>();
        classParamMap.put("examType", CalTypeEnum.examtype_class);
        classParamMap.put("schoolId", user.getSchoolId());
        //如果是校级帐号，查询班级考试的时候，知查询发布后的数据
        if (CalTypeEnum.examtype_school.equals(user.getUserType())) {
            //校级账户
            classParamMap.put("status", ExamEnum.EXAM_STATUS_PUBLISH.getCode().toString());
            paramMap.put("schoolId", user.getSchoolId());
            if (!StringUtils.isEmpty(examParam.getExamName())) {
                paramMap.put("examName", examParam.getExamName());
            }
            if (!StringUtils.isEmpty(examParam.getExamType())) {
                if(CalTypeEnum.examtype_class.equals(examParam.getExamType())){
                    paramMap.put("status", ExamEnum.EXAM_STATUS_PUBLISH.getCode().toString());

                }
                paramMap.put("examType", examParam.getExamType());
            }
            try {
                //排序
                Map<String, Integer> sortMap = new HashMap<>();
                sortMap.put("create_time", 1);
                examModels = exmpRepsitory.findPageBy(paramMap, sortMap, examParam.getPageIndex(), examParam.getPageSize());
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        } else { //班级级账户//如果是班级帐号，查询校级考试的时候，直查询发布后的考试信息
            classParamMap.put("examUnitModels.unitId", user.getClassId());
            schoolParamMap.put("status", ExamEnum.EXAM_STATUS_PUBLISH.getCode().toString());
            paramMap.put("schoolId", user.getSchoolId());
           /* paramMap.put("examUnitModels.unitId",user.getClassId());*/
            if (!StringUtils.isEmpty(examParam.getExamName())) {
                paramMap.put("examName", examParam.getExamName());
            }
            if (!StringUtils.isEmpty(examParam.getExamType()) && CalTypeEnum.examtype_class.equals(examParam.getExamType())) {//班级考试
                paramMap.put("examUnitModels.unitId", user.getClassId());
                paramMap.put("examType", examParam.getExamType());
            } else if (!StringUtils.isEmpty(examParam.getExamType()) && CalTypeEnum.examtype_school.equals(examParam.getExamType())) {//校考
                paramMap.put("examUnitModels.unitId", user.getGradeId());
                paramMap.put("examType", examParam.getExamType());
                paramMap.put("status", ExamEnum.EXAM_STATUS_PUBLISH.getCode().toString());

            }
            try {
                //排序
                Map<String, Integer> sortMap = new HashMap<>();
                sortMap.put("create_time", 1);
                examModels = exmpRepsitory.findPageBy(paramMap, sortMap, examParam.getPageIndex(), examParam.getPageSize());
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        long schoolExamNum = exmpRepsitory.countBy(schoolParamMap);
        long classExamNum = exmpRepsitory.countBy(classParamMap);
        return new ExamVo(schoolExamNum, classExamNum, examModels);
    }


    @Transactional
    @Override
    public ExamModel saveExmp(ExamModel examModel) {
        try {
            ExamModel exam = exmpRepsitory.save(examModel);
            return exam;
        } catch (Exception e) {
            throw new DescribeException(ExceptionEnum.CREATEEXAM_ERROR.getCode(), e.getMessage());
        }
    }

    @Transactional
    @Override
    public ExamModel updateExmp(ExamModel examModel) {
        try {
            ExamModel exam = exmpRepsitory.save(examModel);
            return exam;
        } catch (Exception e) {
            throw new DescribeException(ExceptionEnum.CREATEEXAM_ERROR.getCode(), e.getMessage());
        }
    }
    /**
     * 判断更新后的科目是否存在已导入的试卷
     * @param examModel
     * @param list
     * @return
     */
    public ServiceResponse compUnitSub(ExamModel examModel,List<ExamUnitModel> list){
        ServiceResponse re = ServiceResponseHandle.success("");
        List<ExamUnitModel> sList = examModel.getExamUnitModels();
        //存放年级对应科目的参考信息。key=unitId_subjectId
        Map<String,SubjectScoreModel> sMap = new HashMap<>();
        for (ExamUnitModel e:sList) {
            String uId = e.getUnitId();
            List<SubjectScoreModel> subjectScoreModels = e.getSubjectScoreModels();
            subjectScoreModels.stream().filter(l->Objects.nonNull(l)).forEach(s->{
                sMap.put(uId+"_"+s.getSubjectid(),s);
            });
        }
        Map<String,SubjectScoreModel> tMap = new HashMap<>();
        for (ExamUnitModel e:list) {
            String uId = e.getUnitId();
            List<SubjectScoreModel> subjectScoreModels = e.getSubjectScoreModels();
            subjectScoreModels.stream().filter(l->Objects.nonNull(l)).forEach(s->{
                tMap.put(uId+"_"+s.getSubjectid(),s);
            });
        }
        if(sMap.size()!=tMap.size()){
            re = ServiceResponseHandle.success("修改了科目年级信息，将会删除该考试所有已导入的试卷信息！确认是否删除？");
            re.setCode(ExceptionEnum.USER_CHOICE.getCode());
            return re;
        }
        //循环对比参考单位和科目是否完全一样，并且判断分数
        Iterator<String> iter1 = sMap.keySet().iterator();
        while (iter1.hasNext()){
            String k = iter1.next();
            SubjectScoreModel t = tMap.get(k);
            if(t==null){
                re = ServiceResponseHandle.success("修改了科目年级信息，将会删除该考试所有已导入的试卷信息！确认是否删除？");
                re.setCode(ExceptionEnum.USER_CHOICE.getCode());
                return re;
            }
            SubjectScoreModel s = sMap.get(k);
            if(!s.getToalscore().equals(t.getToalscore())){
                re = ServiceResponseHandle.success("修改了科目年级信息，将会删除该考试所有已导入的试卷信息！确认是否删除？");
                re.setCode(ExceptionEnum.USER_CHOICE.getCode());
                return re;
            }
            else{
                t.setIsEdit(s.getIsEdit());
            }
        }
        return re;
    }
    /**
     * 根据考试ID，查询年级，班级信息
     *
     * @author:
     * @date :2017/11/19
     */
    @Override
    public ServiceResponse getGradeClassInfo(String examId) {
        ExamModel ex = exmpRepsitory.findOne(examId);
        if (ex == null) {
            return ServiceResponseHandle.failed("未查询到考试信息");
        }
        List<GradeAndClassVo> reList = new ArrayList<>();
        //如果是班级考试
        if (CalTypeEnum.examtype_class.equals(ex.getExamType())) {
            GradeAndClassVo v = new GradeAndClassVo();
            v.setGradeId(ex.getGradeId());
            v.setGradeName(ex.getGradeName());
            List<ClassChildVo> l = new ArrayList<>();
            ClassChildVo c = new ClassChildVo();
            c.setClassId(ex.getExamUnitModels().get(0).getUnitId());
            c.setClassName(ex.getExamUnitModels().get(0).getUnitName());
            l.add(c);
            v.setClasses(l);
            reList.add(v);
        }
        //校级考试
        else {
            JWTUserDetails userDetails = SessionUtils.getUserInfo();
            if(CalTypeEnum.examtype_class.equals(userDetails.getUserType())){
                GradeAndClassVo v = new GradeAndClassVo();
                v.setGradeId(userDetails.getGradeId());
                v.setGradeName(userDetails.getGradeName());
                List<ClassChildVo> l = new ArrayList<>();
                ClassChildVo c = new ClassChildVo();
                c.setClassId(userDetails.getClassId());
                c.setClassName(userDetails.getClassName());
                l.add(c);
                v.setClasses(l);
                reList.add(v);
            }
            else{
                List<ExamUnitModel> examUnitModels = ex.getExamUnitModels();
                for (int i = 0; i < examUnitModels.size(); i++) {
                    GradeAndClassVo v = new GradeAndClassVo();
                    v.setGradeId(examUnitModels.get(i).getUnitId());
                    v.setGradeName(examUnitModels.get(i).getUnitName());
                    List<ClassChildVo> l = getAllCalss(v.getGradeId());
                    v.setClasses(l);
                    reList.add(v);
                }
            }
        }
        return ServiceResponseHandle.success(reList);
    }

    /**
     * 通过年级ID获取所有班级信息
     *
     * @param gradeId
     * @return
     */
    public List<ClassChildVo> getAllCalss(String gradeId) {
        List<ClassChildVo> l = new ArrayList<>();
        ServiceResponse res = CmsHttpPostUtil.HttpsGet(classListUrl + gradeId, new HashMap<>(16));
        Object o = res.getData();
        JSONArray j = JSON.parseArray(JSON.toJSONString(o));
        for (int i = 0; i < j.size(); i++) {
            ClassChildVo v = new ClassChildVo();
            JSONObject js = (JSONObject) j.get(i);
            v.setClassName(js.getString("classname"));
            v.setClassId(js.getString("id"));
            l.add(v);
        }
        return l;
    }

    @Override
    public ExamModel findByExampId(String Id) {
        return exmpRepsitory.findOne(Id);
    }

    /**
     * 通过考试ID发布考试信息
     *
     * @author:
     * @date :2017/11/19
     */
    public ServiceResponse publishExam(String examId) {
        ExamModel examModel = exmpRepsitory.findOne(examId);
        if (examModel == null) {
            return ServiceResponseHandle.failed("发布考试失败，未查询到考试信息");
        }
        if (examModel.getExamUnitModels() == null || examModel.getExamUnitModels().size() == 0) {
            return ServiceResponseHandle.failed("发布考试失败，请设置参考班级信息");
        }
        examModel.setStatus(ExamEnum.EXAM_STATUS_PAPER.getCode().toString());
        examModel.setStatusName(ExamEnum.EXAM_STATUS_PAPER.getName());
        exmpRepsitory.save(examModel);
        return ServiceResponseHandle.success("发布考试信息成功，请编辑试卷");
    }

    /**
     * 通过考试ID，年级ID，查询考试对应年级的所有科目信息
     *
     * @param examID
     * @param gradeId
     * @return
     */
    @Override
    public List<SubjectScoreModel> findSubByExamIDAndGraID(String examID, String gradeId) {
        List<SubjectScoreModel> reList = new ArrayList<>();
        ExamModel exam = exmpRepsitory.findOne(examID);
        //判断该考试是班级考试还是校级考试
        if (CalTypeEnum.examtype_class.equals(exam.getExamType())) {
            reList = exam.getExamUnitModels().get(0).getSubjectScoreModels();
        } else {
            List<ExamUnitModel> unitList = exam.getExamUnitModels();
            for (ExamUnitModel unit : unitList) {
                if (gradeId.equals(unit.getUnitId())) {
                    reList = unit.getSubjectScoreModels();
                    return reList;
                }
            }
        }
        return reList;
    }
}
